package com.kimwu.kill.mall.itempre.web.controller;


import com.alibaba.fastjson.JSONObject;
import com.kimwu.kill.mall.item.common.dto.StockGetItemDTO;
import com.kimwu.kill.mall.item.common.vo.ItemVO;
import com.kimwu.kill.mall.itempre.web.rabbitmq.rabbitmq.DriverRabbitmqServce;
import com.kimwu.kill.mall.itempre.web.service.feign.ItemFeignService;
import com.kimwu.kill.mall.redis.lock.annotation.RedisLock;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;

@RestController
@RequestMapping("/itemPre")
@Slf4j
public class ItemPreController {

    @Autowired
    private RedisTemplate redisTemplate;
    @Resource
    private ItemFeignService itemFeignService;

    private static final String REDIS_DATA = "kill:mall:item:pre";


    private static final String TEMP_GOOD = "kill:mall:temp:order";

    /**
     * 用作redis mysql数据同步使用
     * @return
     */
    @PostMapping("/v1/copyData")
    @RedisLock(name = "stockGetItem", value = "stockGetItem", expireTime = 10)
    public String copyData() {
        List<ItemVO> all =
                itemFeignService.getAll();
        all.forEach(i -> {
            redisTemplate.opsForHash().put(REDIS_DATA, i.getId().toString(), JSONObject.toJSONString(i));
            stockFlag.put(i.getId(), true);
        });
        redisTemplate.delete(TEMP_GOOD);
        return "数据同步成功";
    }

    @Autowired
    private DriverRabbitmqServce driverRabbitmqServce;

    private volatile HashMap<Integer, Boolean> stockFlag = new HashMap<>();

    /**
     * 预扣减库存接口  操作redis
     * @param dto
     * @return
     */
    @PostMapping("/v1/stockGetItemPre")
    public String stockGetItemPre(@RequestBody StockGetItemDTO dto) {
        if (stockFlag.get(dto.getItemId()) == null || stockFlag.get(dto.getItemId())) {
            ItemVO itemVO = null;
            // 如果希望调用的内部方法也被拦截，那么必须用过上下文获取代理对象执行调用，而不能直接内部调用，否则无法拦截
            if (null != AopContext.currentProxy()) {
                ItemPreController o = (ItemPreController) AopContext.currentProxy();
                itemVO = o.toStock(dto);
            } else {
                itemVO = toStock(dto);
            }
            if (itemVO != null) {
                return itemVO.getPrice() + "";
            }
        } else {
            log.info("volatile 判断库存已扣减完成，直接返回");
        }
        return "失败";
    }

    @RedisLock(name = "stockGetItem", value = "stockGetItem", expireTime = 10)
    public ItemVO toStock(StockGetItemDTO dto) {
        if (stockFlag.get(dto.getItemId()) == null || stockFlag.get(dto.getItemId())) {
            Object o = redisTemplate.opsForHash().get(REDIS_DATA, dto.getItemId().toString());
            ItemVO i = JSONObject.parseObject(o.toString(), ItemVO.class);
            //如果库存足够购买
            if (i.getStock() > 0 && i.getStock() >= dto.getAmount()) {
                i.setSales(i.getSales() + dto.getAmount());
                i.setStock(i.getStock() - dto.getAmount());
                log.info("【成功】扣减库存 ， 下单数量 {} , 库存 {}", dto.getAmount(), i.getStock());
                //重写reids
                redisTemplate.opsForHash().put(REDIS_DATA, i.getId().toString(), JSONObject.toJSONString(i));
                if (i.getStock() == 0) {
                    stockFlag.put(dto.getItemId(), false);
                }
                //写入rabbitmq死信队列
                driverRabbitmqServce.sendItemMessage(JSONObject.toJSONString(i));
                return i;
            } else {
                log.info("计算判断库存已扣减完成");
                return null;
            }
        } else {
            log.info("【已进入后】volatile 判断库存已扣减完成，直接返回");
            return null;
        }
    }


}
